package com.dmz.etc.server.utils.secure;

import com.dmz.etc.server.config.AppConfig;
import com.dmz.etc.server.config.constant.DmzConfig;
import com.dmz.etc.server.utils.SpringUtil;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author lee
 */
public class CryptoUtil {

    // 加解密统一使用的编码方式
    private final static String ENCODING = DmzConfig.GLOBAL_ENCODING;

    public static String encrypt(String plainText) throws Exception {
        AppConfig appConfig = SpringUtil.getBean(AppConfig.class);
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(appConfig.getKey().getBytes(), "DESede");
        IvParameterSpec iv = new IvParameterSpec(appConfig.getIv());

        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(ENCODING));
        return bytesToHex(encryptedBytes);
    }

    public static String decrypt(String encryptedText) throws Exception {
        AppConfig appConfig = SpringUtil.getBean(AppConfig.class);
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(appConfig.getKey().getBytes(), "DESede");
        IvParameterSpec iv = new IvParameterSpec(appConfig.getIv());

        cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
        byte[] decryptedBytes = cipher.doFinal(hexToBytes(encryptedText));
        return new String(decryptedBytes, ENCODING);
    }

    // 字节转十六进制字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    // 十六进制字符串转字节数组
    private static byte[] hexToBytes(String hexStr) {
        int len = hexStr.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4)
                    + Character.digit(hexStr.charAt(i+1), 16));
        }
        return data;
    }

    public static byte[] encrypt(String plainText, byte[] keyBytes) throws Exception {
        AppConfig appConfig = SpringUtil.getBean(AppConfig.class);
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
//        Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "DESede");
        IvParameterSpec iv = new IvParameterSpec(appConfig.getIv());

        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        return cipher.doFinal(plainText.getBytes(ENCODING));
    }

    public static byte[] encrypt(byte[] plainText, byte[] keyBytes) throws Exception {
        AppConfig appConfig = SpringUtil.getBean(AppConfig.class);
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
//        Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "DESede");
        IvParameterSpec iv = new IvParameterSpec(appConfig.getIv());

        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        return cipher.doFinal(plainText);
    }

    public static byte[] decrypt(byte[] encryptedBytes, byte[] keyBytes) throws Exception {
        AppConfig appConfig = SpringUtil.getBean(AppConfig.class);
        //Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "DESede");
        IvParameterSpec iv = new IvParameterSpec(appConfig.getIv());

        cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
        return cipher.doFinal(encryptedBytes);
    }

    public static byte[] getKey(byte[] keyStr) {
        byte[] dynamicKey = new byte[24];
        System.arraycopy(keyStr, 0, dynamicKey, 0, 16);
        System.arraycopy(keyStr, 0, dynamicKey, 16, 8);
        return dynamicKey;
    }
}

